<?php
namespace App\Common\Cla\Rbac\Role;

use App\Common as com;

class OfId extends com\Cla\ClaBase {

	use com\Cla\ClaBase\Traits\GoPool;

	/**
	 * @var int
	 */
	private int $_roleId;

	public function __construct( int $roleId ) {
		$this->_roleId = $roleId;
		//
		parent::__construct();
	}

	/**
	 * 获取roleId
	 * @return int|null
	 */
	public function getRoleId(  ) {
		return $this->_roleId;
	}

	/**
	 * @return com\Model\RbacRole\DataManager
	 */
	public function goDirectDataManaerOfRead(  ):com\Model\RbacRole\DataManager {
		return $this->goPool( __FUNCTION__, function(){
			return $this->goDirectDataManaer_New();
		} );
	}

	/**
	 * @return com\Model\RbacRole\DataManager
	 */
	public function goDirectDataManaer_New(  ):com\Model\RbacRole\DataManager {
		return com\Model\RbacRole::dataManager( [
			'id' => $this->getRoleId(),
		] );
	}

	/**
	 * @return com\Lib\Cache\KeyDB
	 */
	private function goRoleCacheKeyDb(  ):com\Lib\Cache\KeyDB {
		return $this->goPool( __FUNCTION__, function(){
			return com\Lib\Cache\KeyDB::use( 'rbacRole.permissionIds' )->param( $this->getRoleId() );
		} );
	}

	private function clearBindPermissionIdsOfCache(  ):void {
		$this->goRoleCacheKeyDb()->del();
	}

	/**
	 * 获取已绑定的权限项id(缓存)
	 * @param bool $force 是否强制获取数据库。
	 * @return string [逗号分割] [前后逗号]
	 */
	private function getBindPermissionIdsStrOfCache( $force = false ):string {
		// 读取缓存
		if( ! $force ){
			$permissionIds = $this->goRoleCacheKeyDb()->get();
			if( $permissionIds !== false ) return com\Lib\Fun\Array_::toStr( $permissionIds );
		}
		//
		$permissionids = $this->goDirectDataManaerOfRead()->value( 'permission_ids', '' );
		// 保存到缓存
		$this->goRoleCacheKeyDb()->set( $permissionids, 180 );
		//
		return $permissionids;
	}

	/**
	 * 写入权限项(自动绑定插入或更新)
	 * @param array $permissionIdsArray 待写入权限项ids
	 * @return void
	 */
	private function updatePermissionIds( array $permissionIdsArray ):void {
		sort( $permissionIdsArray );
		$permissionIdsStr = implode( ",", $permissionIdsArray );
		if( ! empty( $permissionIdsStr ) ){
			$permissionIdsStr = ",{$permissionIdsStr},";
		}
		// 写入
		$this->goDirectDataManaer_New()
			->setData_PermissionIds( $permissionIdsStr )
			->save();
		// 清空缓存
		$this->clearBindPermissionIdsOfCache();
	}

	/**
	 * 绑定权限（追加）
	 * @param array $authSids
	 * @return void
	 */
	public function bindsOfSid( array $authSids ):void {
		// ...
		$waitPermissionIds = $this->getPermissionIdsOfSid( $authSids );
		$permissionIdsStr = $this->getBindPermissionIdsStrOfCache();
		$permissionIds = com\Lib\Fun\Array_::toArray( $permissionIdsStr );
		// 建立数组索引
		$permissionIdsArrayIndex = com\Lib\Fun\Array_::arrayFlip( $permissionIds, [
			'newValue' => 1 //
		] );

		foreach( $waitPermissionIds as $permissionId ){
			if( ! isset( $permissionIdsArrayIndex[ $permissionId ] ) ){
				// 加入
				$permissionIdsArrayIndex[ $permissionId ] = 1;
			}
		}
		// 写入
		$this->updatePermissionIds( array_keys( $permissionIdsArrayIndex ) );
	}

	/**
	 * 覆盖权限（清空旧权限）
	 * @param array $authSids
	 * @return void
	 */
	public function coverBindsOfSid( array $authSids ):void {
		// ...
		if( ! empty( $authSids ) ){
			$waitPermissionIds = $this->getPermissionIdsOfSid( $authSids );
		}else{
			$waitPermissionIds = [];
		}
		// 写入
		$this->updatePermissionIds( $waitPermissionIds );
	}

	/**
	 * 解绑权限
	 * @param array $authSids
	 * @return void
	 */
	public function unBindsOfSid( array $authSids ):void {
		// ...
		$waitPermissionIds = $this->getPermissionIdsOfSid( $authSids );
		$permissionIdsStr = $this->getBindPermissionIdsStrOfCache();
		$permissionIds = com\Lib\Fun\Array_::toArray( $permissionIdsStr );
		// 建立数组索引
		$permissionIdsArrayIndex = com\Lib\Fun\Array_::arrayFlip( $permissionIds, [
			'newValue' => 1 //
		] );
		foreach( $waitPermissionIds as $permissionId ){
			if( isset( $permissionIdsArrayIndex[ $permissionId ] ) ){
				// 销毁
				unset( $permissionIdsArrayIndex[ $permissionId ] );
			}
		}
		// 写入
		$this->updatePermissionIds( array_keys( $permissionIdsArrayIndex ) );
	}

	/**
	 * 检查是否已绑定(根据sid)
	 * @param array $authSids
	 * @return bool [true]已绑定的 [false]未绑定
	 */
	public function isBindsOfSid( array $authSids ):bool {
		// ...
		if( empty( $authSids ) ){
			throw com\Lib\Err\Exception::makeOfNew( '不能为空', com\Lib\Err\Code::$sysDataError );
		}
		//
		$ckeckPermissionIds = $this->getPermissionIdsOfSid( $authSids );
		//
		return $this->isBindsOfId( $ckeckPermissionIds );
	}

	/**
	 * 检查是否已绑定(根据id)
	 * @param array $ckeckPermissionIds
	 * @return bool [true]已绑定的 [false]未绑定
	 */
	public function isBindsOfId( array $ckeckPermissionIds ):bool {
		// ...
		if( empty( $ckeckPermissionIds ) ){
			throw com\Lib\Err\Exception::makeOfNew( '不能为空', com\Lib\Err\Code::$sysDataError );
		}
		//
		$permissionIdsStr = $this->getBindPermissionIdsStrOfCache();
		foreach( $ckeckPermissionIds as $permissionId ){
			if( strpos( $permissionIdsStr, ",{$permissionId}," ) === false ){
				return false;
			}
		}
		//
		return true;
	}

	/**
	 * 获取权限项id（根据sid）
	 * @param array $authSids
	 * @return array
	 */
	private function getPermissionIdsOfSid( array $authSids ):array {
		// 去重
		$authSids = com\Lib\Fun\Array_::toArray( $authSids, [ 'unique' => 1 ] );
		//
		$rbacPermissionManager = com\Model\RbacPermission::dataManager();
		$rbacPermissionManager->newData_Sid()->whereIn( $authSids );
		$permissionIds = $rbacPermissionManager->goModelQuery()->pluck( 'id' )->toArray();
		// 检查
		if( count( $permissionIds ) != count( $authSids ) ){
			throw com\Lib\Err\Exception::makeOfNew( '数据不一致', com\Lib\Err\Code::$sysDataError );
		}
		return $permissionIds;
	}
}
